﻿using KAKA.Domain;
using KAKA.Repository;
using Morus;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace KAKA.Infrastructure
{
    public class TextMessageSender : ITextMessageSender
    {
        private readonly string _templateDirectory;
        private readonly string _serialNumber = "3SDK-EMY-0130-LGYNP";
        private readonly string _password = "kakamico292209";
        private readonly string _suffix;

        private readonly string _template_MobileVerification = "MobileVerification";

        public TextMessageSender(string serialNumber, string password, string suffix, string templateDirectory)
        {
            Check.Argument.IsNotEmpty(serialNumber, "serialNumber");
            Check.Argument.IsNotEmpty(password, "password");

            _templateDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, templateDirectory);
            _serialNumber = serialNumber;
            _password = password;
            _suffix = suffix;
        }

        public void SendProof(Proof proof)
        {
            var body = PrepareMessageBody(_template_MobileVerification, "VerificationCode", proof.Value);

            using (var uow = UnitOfWork.Begin())
            {
                var userRepository = IoC.Resolve<UserRepository>();
                var user = userRepository.Get(proof.User.Id);
                user.Proofs.First(r => r.Id == proof.Id).Message = body;

                uow.Commit();
            }

            SendAsync(proof.Mobile, body);
        }

        private void Send(string number, string message)
        {
#if (DEBUG)
            Debug.WriteLine(@"Send message to {0}, content: {1}".FormatWith(number, message));
#else
            try
            {
                using (SMS.SDKService sms = new SMS.SDKService())
                {
                    sms.sendSMS(_serialNumber, _password, string.Empty, new string[] { number }, message, string.Empty, "GBK", 1);
                }
            }
            catch (Exception ex)
            {
                Log.Exception(ex);
            }
#endif
        }

        private void SendAsync(string number, string message)
        {
            ThreadPool.QueueUserWorkItem(state => Send(number, message));
        }

        private string ReadFileFrom(string templateName)
        {
            string filePath = string.Concat(Path.Combine(_templateDirectory, templateName), ".txt");

            string body = File.ReadAllText(filePath);

            return body;
        }

        private string PrepareMessageBody(string templateName, params string[] pairs)
        {
            string body = GetMessageBodyOfTemplate(templateName);

            for (var i = 0; i < pairs.Length; i += 2)
            {
                body = body.Replace("##[{0}]##".FormatWith(pairs[i]), pairs[i + 1]);
            }

            return string.Concat(body, _suffix);
        }

        private string GetMessageBodyOfTemplate(string templateName)
        {
            var cacheKey = "messageTemplate:{0}".FormatWith(templateName);
            string body;

            Cache.TryGet(cacheKey, out body);

            if (string.IsNullOrEmpty(body))
            {
                body = ReadFileFrom(templateName);

                if ((!string.IsNullOrEmpty(body)) && (!Cache.Contains(cacheKey)))
                {
                    Cache.Set(cacheKey, body);
                }
            }

            return body;
        }
    }
}
